﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using GeneralDFS.BusinessLogical;
using GeneralDFS.BusinessLogical.Nodes;
using GeneralDFS.BusinessLogical.Statistics;
using GeneralDFS.DataEntity.Nodes;
using GeneralDFS.DataEntity.Statistics;
using GeneralDFS.Interface.Agent;
using NIF.MobileActors.Core;
using NIF.MobileActors.Hosts;

namespace AgentTest
{
    [Serializable]
    public class DataNodeActor : ActorBase<IEntry>, IEntry
    {
        private Queue<IPEndPoint> _hosts;
        public Queue<IPEndPoint> Hosts
        {
            get { return _hosts; }
            set { _hosts = value; }
        }

        private IPEndPoint localHost;
        public IPEndPoint LocalHost
        {
            get { return localHost; }
            set { localHost = value; }
        }
        private bool isLastHost = false;
        public bool IsLastHost
        {
            get { return isLastHost; }
        }
        private bool isFirstHost = true;
        public bool IsFirstHost
        {
            get { return isFirstHost; }
        }

        public List<DataNodeCounter> DataNodeStatistics = new List<DataNodeCounter>();

        protected override void Receive(Action<IEntry> message)
        {
            message(this);
        }

        protected override void ResumeState(IActor actNewState)
        {
            Debug.Assert(actNewState is DataNodeActor);
            var dataNodeActor = (DataNodeActor) actNewState;
            _hosts = dataNodeActor.Hosts;
            isLastHost = dataNodeActor.isLastHost;
            isFirstHost = dataNodeActor.isFirstHost;
            localHost = dataNodeActor.localHost;
            DataNodeStatistics=dataNodeActor.DataNodeStatistics;
        }

        public override void OnDispatched()
        {
            ActorProxy<IEntry> proxy = RemotingHost.LocalFacade.GetActorProxy<IEntry>(this.ID);
            proxy.Post(h => h.Excute());
        }

        public void Excute()
        {
            if (_hosts.Count == 0 && isFirstHost == true)
            {
                Print("There is not any nodes");
            }
            else if (isFirstHost && _hosts.Count != 0)
            {
                Print("Start go to the Nodes to search Information....");
                var ipEndPoint = _hosts.Dequeue();
                isFirstHost = false;
                RemotingHost.DispatchActorTo(this, ipEndPoint);
            }
            else if (!isFirstHost)
            {
                if (RemotingHost.Node != null && RemotingHost.Node is DataNode)
                {
                    var nodeID = ((DataNode) RemotingHost.Node).DataNodeInfo as DataNodeID;
                    var counter = new DataNodeCounter
                        {
                            Index = nodeID.Index,
                            Ip = nodeID.Ip,
                            Name = nodeID.Name,
                            RpcPort = nodeID.RpcPort,
                            TcpPort = nodeID.TcpPort,
                            Speed = Speed.GetInstance().GetSpeed().ToString(),
                            BlockCounter = FSVolume.GetInstance().GetTotalBlockNum()
                        };

                    DataNodeStatistics.Add(counter);
                    try
                    {

                        if (_hosts.Count == 0)
                        {
                            Console.WriteLine("you are the last one");
                            isLastHost = true;
                            isFirstHost = true;
                            RemotingHost.DispatchActorTo(this, localHost);
                            return;
                        }
                        else
                        {
                            var ipEndPoint = _hosts.Dequeue();
                            RemotingHost.DispatchActorTo(this, ipEndPoint);
                        }
                    }
                    catch (Exception ex)
                    {
                        Print(ex.Message);
                    }

                }


            }
            if (isLastHost)
            {
                Console.WriteLine("you have finished:");
            }
        }

        public void Print(string message)
        {
            Console.WriteLine(message);
        }
    }
}
